#include "inc/hw_memmap.h"
#include "flash.h"
#include "wdt_a.h"
#include "gpio.h"
#include "ConfigMem.h"

//*****************************************************************************
//Number of bytes being copied
//*****************************************************************************
#define NUMBER_OF_BYTES   128

//*****************************************************************************
//Calibration data to be written into flash
//*****************************************************************************
#define SEGMENT_SIZE 512 // bytes
#define NUM_SEGMENTS 12
#pragma DATA_SECTION(flashImage, ".cfgMem")
unsigned char flashImage[5029] = {0};
//const unsigned char * pc = (unsigned char *)&flashImage[0];// = (unsigned char *)0x6800;
//#pragma DATA_SECTION(temp, ".cfgMem")
unsigned char temp = 0;

unsigned char calibration_data_char [16];
unsigned char ramArr [16];
//*****************************************************************************
//INFO address in flash to which data is written into
//*****************************************************************************
#define INFOD_START   (0x1800)
#define INFOC_START   (0x1880)
#define INFOB_START   (0x1900)
#define INFOA_START   (0x1980)
//#define FLASH_CFG_START (0xE780)
#define FLASH_CFG_START (0x5C00)
//#define FLASH_CFG_START (0X010000)
#define BANK0a_START	(0X005C00)
#define BANK0b_START	(0X040000)
#define BANK1_START		(0X010000)
#define BANK2_START		(0X020000)
#define BANK3_START		(0X030000)

//*****************************************************************************
//Delay cycles
//*****************************************************************************
#define DELAY_TIME 1000000

//*****************************************************************************
//Function prototypes
//*****************************************************************************
void configMem_resetMem(void);
void configMem_eraseAllSegments(void);
void flash_thread(void);
unsigned char configMem_getRevision(unsigned int posn);
void configMem_init(void);

// note: WDT should be held
void configMem_init(void)
{
	unsigned char c = __data20_read_char(BANK1_START);
	unsigned short s = __data20_read_short(BANK1_START);
	unsigned long ln = __data20_read_long(BANK1_START);

	for (c=0; c<16; c++)
	{
		calibration_data_char[c] = c;
		ramArr[c] = 20 - c;

	}
	configMem_resetMem();
	configMem_updateFLASH(calibration_data_char, 16);
	configMem_copyToRAM(ramArr, 16, 0);
	configMem_eraseAllSegments();
	configMem_updateFLASH(calibration_data_char, 16);
}

void configMem_resetMem(void)
{
	FLASH_memoryFill8(FLASH_BASE,0x00,(unsigned char *)FLASH_CFG_START,(SEGMENT_SIZE*NUM_SEGMENTS));
}
void configMem_eraseAllSegments(void)
{
	unsigned short status;
	do {
		unsigned int sector;
		unsigned char * p = (unsigned char *)FLASH_CFG_START;
		for (sector = 0; sector < NUM_SEGMENTS; sector++)
		{
			p = sector * 512 + (unsigned char *)FLASH_CFG_START;
			FLASH_segmentErase(FLASH_BASE, (unsigned char *)p);
		}
		status = FLASH_eraseCheck(FLASH_BASE, (unsigned char *)FLASH_CFG_START,SEGMENT_SIZE*NUM_SEGMENTS);
	} while (status == STATUS_FAIL);
}
void configMem_copyToRAM(unsigned char * RAMdest, unsigned int numberOfBytes, unsigned int offset)
{
	//unsigned char * flash_ptr = (unsigned char *)FLASH_CFG_START+8+offset;
	unsigned char * flash_ptr = (unsigned char *)FLASH_CFG_START+offset;
	while (numberOfBytes > 0)
	{
		//Copy byte from Flash to RAM
		*RAMdest++ = *flash_ptr++;
		numberOfBytes--;
	}

}
void configMem_updateFLASH(unsigned char * RAMsrc, unsigned int size)
{
	if (STATUS_FAIL == FLASH_eraseCheck(FLASH_BASE,(unsigned char *)FLASH_CFG_START, size))
			configMem_eraseAllSegments();
	FLASH_write8(FLASH_BASE, RAMsrc, (unsigned char *)FLASH_CFG_START, size);
}
unsigned char configMem_getRevision(unsigned int posn)
{
	unsigned char rtn = flashImage[1123];
	return rtn;
}
unsigned char configMem_getByte(unsigned int posn)
{
	unsigned char rtn = flashImage[posn];
	return rtn;
}
void configMem_setRevision(unsigned char rev)
{
	FLASH_write8(FLASH_BASE, &rev, (unsigned char *)&flashImage[1123], 1);
}

void flash_thread(void)
{

}
